package com.crpc.core.proxy.handler;

import com.crpc.common.constant.MessageFormatConstant;
import com.crpc.core.compress.Compressor;
import com.crpc.core.compress.CompressorFactory;
import com.crpc.core.serialize.Serializer;
import com.crpc.core.serialize.SerializerFactory;
import com.crpc.core.transport.message.CrpcResponse;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.extern.slf4j.Slf4j;

import static com.crpc.common.constant.MessageFormatConstant.*;

/**
 * <pre>
 *     0    1    2    3    4   5    6    7    8    9    10   11   12   13   14   15   16  17    18   19   20   21   22
 *     +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
 *     /        magic      /ver / head len/  full length      /code/ ser/com /            requestId                  /
 *     +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
 *     /                                                                                                             /
 *     /                                  body                                                                       /
 *     /                                                                                                             /
 *     +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+
 * </pre>
 * <p>
 * <p>
 * <p>
 * <p>
 * <p>
 * <p>
 * 4b magic 魔数值 类似于鉴定标志-> crpc.getBytes()
 * 1b version 版本
 * 2b header length 头部长度
 * 4b full length 总的报文长度
 * 1b requestType
 * 1b serialize
 * 1b compress
 * 8b requestId
 * <p>
 * body
 *
 * @author wzy
 * @version 1.0
 * @description: 出栈时第一个经过的处理器
 * @date 2023/9/26 15:03
 */
@Slf4j
public class CrpcResponseEncoder extends MessageToByteEncoder<CrpcResponse> {
    @Override
    protected void encode(ChannelHandlerContext channelHandlerContext, CrpcResponse crpcResponse, ByteBuf byteBuf) throws Exception {

        //魔数
        byteBuf.writeBytes(MAGIC);
        //版本号
        byteBuf.writeByte(MessageFormatConstant.VERSION);
        //2个字节头部长度
        byteBuf.writeShort(MessageFormatConstant.HEADER_LENGTH);
        //body长度
        byteBuf.writerIndex(byteBuf.writerIndex() + MessageFormatConstant.FULL_FIELD_Length);
        //三个类型,请求类型,序列化类型,压缩类型
        byteBuf.writeByte(crpcResponse.getCode());
        byteBuf.writeByte(crpcResponse.getSerializeType());
        byteBuf.writeByte(crpcResponse.getCompressType());
        //请求id
        byteBuf.writeLong(crpcResponse.getRequestId());
        byteBuf.writeLong(crpcResponse.getTimeStamp());
        //body内容
        Serializer serializer = SerializerFactory.getSerializer(crpcResponse.getSerializeType()).getSerializer();
        byte[] bodyBytes = serializer.serialize(crpcResponse.getBody());
        //  压缩
        if (bodyBytes != null && bodyBytes.length != 0) {
            Compressor compressor = CompressorFactory.getCompressor(crpcResponse.getCompressType()).getCompressor();
            bodyBytes = compressor.compress(bodyBytes);
        }
        if (bodyBytes != null) {
            byteBuf.writeBytes(bodyBytes);
        }
        int bodyLength = bodyBytes == null ? 0 : bodyBytes.length;
        //保存当前写指针的位置
        int writerIndex = byteBuf.writerIndex();
        byteBuf.writerIndex(MAGIC.length + VERSION_LENGTH + HEADER_FIELD_LENGTH);
        byteBuf.writeInt(MessageFormatConstant.HEADER_LENGTH + bodyLength);
        //指针归位
        byteBuf.writerIndex(writerIndex);
        log.info("响应：{}，已经在服务端完成响应的编码", crpcResponse.getRequestId());
    }
}
